fix(cryptography): skip KDF-iterations floor on decrypt path [STUD-80534]#577
Open
alexandru-petre wants to merge 1 commit into
Open
fix(cryptography): skip KDF-iterations floor on decrypt path [STUD-80534]#577alexandru-petre wants to merge 1 commit into
alexandru-petre wants to merge 1 commit into
Conversation
…534] The MinKdfIterations=1000 floor in SymmetricInteropHelper.ValidateInteropSettings applied to both encrypt and decrypt. On decrypt it wrongly blocked legitimate third-party blobs produced with a low iteration count (e.g. openssl enc -iter 100), which are mathematically decryptable. Thread an isDecrypt flag through ValidateInteropSettings and RunSymmetricWithKeyLifecycle (and CryptographyService.ValidateSymmetric for the coded-workflow path); skip only the positive-but-below-1000 floor on decrypt. Encrypt-side floor, negative rejection, and zero-means-default are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adjusts the Cryptography package’s symmetric interop validation so that the MinKdfIterations = 1000 floor is enforced only on encrypt, not on decrypt, enabling successful decryption of third‑party OpenSslEnc payloads produced with low PBKDF2 iteration counts while preserving the encrypt-side guardrail.
Changes:
- Thread an
isDecryptflag throughSymmetricInteropHelper.ValidateInteropSettings/RunSymmetricWithKeyLifecycleand skip the positive-below-floor iteration check on decrypt. - Update decrypt activity call sites (DecryptText/DecryptFile) and coded-workflow
CryptographyServiceto passisDecrypt: trueon decrypt validation paths. - Add/extend tests to pin decrypt-accepts-low-iterations behavior while keeping encrypt refusal and negative-iteration rejection.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| Activities/Cryptography/UiPath.Cryptography/SymmetricInteropHelper.cs | Adds isDecrypt direction context to validation and lifecycle helper to skip the encrypt-only iteration floor during decrypt. |
| Activities/Cryptography/UiPath.Cryptography.Activities/DecryptText.cs | Passes isDecrypt: true when running symmetric decrypt lifecycle. |
| Activities/Cryptography/UiPath.Cryptography.Activities/DecryptFile.cs | Passes isDecrypt: true when running symmetric decrypt lifecycle. |
| Activities/Cryptography/UiPath.Cryptography.Activities.Tests/SymmetricInteropHelperTests.cs | Adds validator theory ensuring decrypt skips the positive iteration floor while negatives still throw. |
| Activities/Cryptography/UiPath.Cryptography.Activities.Tests/ExternalInteropInProcessTests.cs | Adds interop regression tests covering decrypting low-iteration OpenSslEnc blobs and ensuring encrypt still refuses. |
| Activities/Cryptography/UiPath.Cryptography.Activities.API/Services/CryptographyService.cs | Plumbs decrypt/encrypt direction into the service’s symmetric validation path. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Context
The Cryptography package's symmetric encrypt/decrypt activities (EncryptText/File, DecryptText/File) and the coded-workflow
CryptographyServiceall route throughSymmetricInteropHelper, which validates cross-property invariants before dispatching toCryptographyHelper. One invariant is aMinKdfIterations = 1000floor on the PBKDF2 iteration count — part of the third-party interop work (STUD=64429 → STUD=80231) that introduced theOpenSslEncwire format.Problem Statement
The 1000-iteration floor was enforced on both encrypt and decrypt. On decrypt this is wrong: a third-party blob produced with a low iteration count (e.g.
openssl enc -pbkdf2 -iter 100 -md sha256 -salt -k <pw>) is mathematically decryptable — the producer chose 100, we can derive the matching key/IV — but the package threwValidation_KdfIterations_BelowMinimumbefore reaching the decrypt code. This defeats the headline interop premise ofOpenSslEncfor anyone consuming low-iteration data.Analysis
RunSymmetricWithKeyLifecycle(andCryptographyService.ValidateSymmetric) called the single validator with no direction context, so the floor — correct only on encrypt, where it prevents emitting weak ciphertext — also gated decrypt.Behavior Before This PR
Decrypting an
OpenSslEncblob produced atiter=100withKdfIterations=100throwsArgumentException(Validation_KdfIterations_BelowMinimum) before any decryption is attempted, even though the key/IV can be derived exactly.Behavior After This PR
The same decrypt succeeds and returns the plaintext. Encrypt with
KdfIterations=100still throws (floor preserved); negative iterations are still rejected on both paths; andKdfIterations=0still resolves to the format default on both paths.Implementation
A
bool isDecryptflag (optional, defaults tofalse) is threaded throughValidateInteropSettingsandRunSymmetricWithKeyLifecycle; only the positive-but-below-1000 branch is gated on!isDecrypt. The negative-iteration rejection is deliberately left unconditional. The optional default keeps all existing source callers source-compatible (the helper is documented as package-internal glue).How to Test
dotnet test Activities/Activities.Cryptography.sln— full suite green (784 + 123).dotnet test --filter "FullyQualifiedName~OpenSslEnc_AesCbc_DecryptHonoursLowKdfIterations"fails ondevelop(ArgumentException) and passes on this branch.OpenSslEnc_AesCbc_EncryptStillRefusesLowKdfIterations,OpenSslEnc_AesCbc_NegativeKdfIterations_RejectedOnBothDirections, and theValidate_KdfIterations_AtFloor_DecryptSkipsPositiveFloortheory.